#pragma once

#include <string>
#include <vector>
#include "../Config/Field.h"

class IData
{
public:
    IData();
    virtual ~IData();

	class Fields
	{
	public:
		Fields() : buf_size_(20480), field_lens_size_(300000)
		{
			buf_ = new char[buf_size_];
			field_lens_ = new int[field_lens_size_];

			clear();
		}

		Fields(int buf_size, int field_lens_size) : buf_size_(buf_size), field_lens_size_(field_lens_size)
		{
			buf_ = new char[buf_size_];
			field_lens_ = new int[field_lens_size_];

			clear();
		}
	
		~Fields()
		{
			if (buf_ != nullptr)
			{
				delete[]buf_;
			}

			if (field_lens_ != nullptr)
			{
				delete[]field_lens_;
			}
		}

		void clear()
		{
			buf_pos_ = 0;
			field_index_ = 0;
			
			memset(buf_, 0, buf_size_);
			memset(field_lens_, 0, sizeof(int) * field_lens_size_);
		}

		void resetPos()
		{
			buf_pos_ = 0;
			field_index_ = 0;
		}


		void add_field(const char* field, int field_len)
		{
			if (buf_pos_ + field_len > buf_size_)
			{
				buf_size_ *= 2;
				char *temp_buf = new char[buf_size_];
				memset(temp_buf, 0, buf_size_);

				memcpy(temp_buf, buf_, buf_pos_);

				delete[]buf_;
				buf_ = temp_buf;
			}

			if (field_index_ + 1 >= field_lens_size_)
			{
				field_lens_size_ *= 2;
				int *temp_field_lens = new int[field_lens_size_];
				memset(temp_field_lens, 0, field_lens_size_);

				memcpy(temp_field_lens, field_lens_, sizeof(int) * field_index_);

				delete[]field_lens_;
				field_lens_ = temp_field_lens;
			}

			if (field != nullptr && field_len > 0) 
			{
				memcpy(buf_ + buf_pos_, field, field_len);
				field_lens_[field_index_] = field_len;
			}
			else {
				field_lens_[field_index_] = 0;
				field_len = 0;
			}

			buf_pos_ += field_len;
			++field_index_;
		}

		int field_len(int index) { return field_lens_[index]; }

		const char *buf() const { return buf_; }

		const int *field_lens() const { return field_lens_; }

		char *buf() { return buf_; }

		int *field_lens() { return field_lens_; }

		int buf_size() { return buf_size_; }

		int field_lens_size() { return field_lens_size_; }

	public:
		int buf_pos_;
		int field_index_;

	private:
		int buf_size_;
		char *buf_;

		int field_lens_size_;
		int *field_lens_;
	};

	virtual int num_rows(const std::string &table) = 0;

    virtual bool select(const std::string &sql, Fields &fields, int &row_num, std::vector<Field> *columns) = 0;

    virtual bool select(const std::string &sql, const std::vector<std::string> &args, Fields &fields, int &row_num, std::vector<Field> *columns) = 0;

    virtual bool insert(const std::string &table, Fields &fields, int row_num, std::vector<Field> &columns) = 0;

	virtual bool isDatabaseExists(const std::string &database) = 0;

	virtual int createDatabase(const std::string &database) = 0;

	virtual int useDatabase(const std::string &database) = 0;

	virtual bool isTableExists(const std::string &table) = 0;

    virtual int createTable(const std::string &table, std::vector<Field> &columns) = 0;

    virtual int showTables(std::vector<std::string> &tables) = 0;

    virtual int showColumns(const std::string &table, std::vector<Field> &columns) = 0;

public:
	static int zero_size_;
};

